﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ExtendedKeystrokeSettings.xaml.cs" company="arvystate.net">
//   arvystate.net
// </copyright>
// <summary>
//   Interaction logic for ExtendedKeystrokeSettings.xaml
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace PresentationAid.Lib.GestureEngines.GestureSettings
{
    using System;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;

    using NLog;

    using PresentationAid.Lib.Enums;

    /// <summary>
    /// Interaction logic for ExtendedKeystrokeSettings
    /// </summary>
    public partial class ExtendedKeystrokeSettings
    {
        #region Static Fields

        /// <summary>
        /// The logger.
        /// </summary>
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

        #endregion

        #region Fields

        /// <summary>
        /// The extended keystroke engine.
        /// </summary>
        private readonly ExtendedKeystrokeEngine extendedKeystrokeEngine;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ExtendedKeystrokeSettings"/> class.
        /// </summary>
        /// <param name="engine">
        /// The engine.
        /// </param>
        public ExtendedKeystrokeSettings(GestureEngine engine)
            : base(engine)
        {
            Logger.Trace("Init: ExtendedKeystrokeSettings");

            this.extendedKeystrokeEngine = (ExtendedKeystrokeEngine)engine;

            this.InitializeComponent();
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// Initializes setting boxes
        /// </summary>
        public override void CreateSettings()
        {
            // Create settings once.
            if (this.SettingGrid.RowDefinitions.Count > 1)
            {
                return;
            }

            for (int i = 1; i < Enum.GetNames(typeof(GestureCommand)).Length; i++)
            {
                this.SettingGrid.RowDefinitions.Add(new RowDefinition());

                // Create gesture combobox
                TextBlock textBlock = new TextBlock
                                          {
                                              Text = ((GestureCommand)i).ToString(), 
                                              Margin = new Thickness(15, 0, 15, 15), 
                                              FontSize = 16, 
                                              VerticalAlignment = VerticalAlignment.Center
                                          };

                Grid.SetRow(textBlock, i);

                this.SettingGrid.Children.Add(textBlock);

                // Create key combobox
                ComboBox comboBox = new ComboBox();

                // Handle control command
                ComboBoxItem item = new ComboBoxItem { Content = new TextBlock(new Bold(new Run("Take Control"))) };

                comboBox.Items.Add(item);

                for (int x = 0; x < Enum.GetNames(typeof(Key)).Length; x++)
                {
                    item = new ComboBoxItem { Content = ((Key)x).ToString() };

                    comboBox.Items.Add(item);
                }

                comboBox.Margin = new Thickness(0, 0, 15, 15);
                comboBox.SelectionChanged += this.OnComboBoxSelectionChanged;

                Grid.SetRow(comboBox, i);
                Grid.SetColumn(comboBox, 1);

                this.SettingGrid.Children.Add(comboBox);

                // Create alternate key combobox
                comboBox = new ComboBox();

                for (int x = 0; x < Enum.GetNames(typeof(Key)).Length; x++)
                {
                    item = new ComboBoxItem { Content = ((Key)x).ToString() };

                    comboBox.Items.Add(item);
                }

                comboBox.Margin = new Thickness(0, 0, 15, 15);
                comboBox.SelectionChanged += this.OnComboBoxSelectionChanged;

                Grid.SetRow(comboBox, i);
                Grid.SetColumn(comboBox, 2);

                this.SettingGrid.Children.Add(comboBox);
            }
        }

        /// <summary>
        /// Adjusts combo boxes to current settings
        /// </summary>
        public override void LoadSettings()
        {
            Logger.Debug("Method: LoadSettings");

            // Can assume that the grid is setuped here
            for (int i = 1; i < Enum.GetNames(typeof(GestureCommand)).Length; i++)
            {
                // Get both ComboBoxes
                ComboBox keyMap =
                    (ComboBox)
                    this.SettingGrid.Children.Cast<UIElement>()
                        .First(e => (Grid.GetRow(e) == i) && (Grid.GetColumn(e) == 1));

                // Control Gesture
                if ((GestureCommand)i == this.extendedKeystrokeEngine.ControlGesture)
                {
                    keyMap.SelectedIndex = 0;
                }
                else
                {
                    ComboBox alternateMap =
                        (ComboBox)
                        this.SettingGrid.Children.Cast<UIElement>()
                            .First(e => (Grid.GetRow(e) == i) && (Grid.GetColumn(e) == 2));

                    // Loop through all keys
                    for (int x = 0; x < Enum.GetNames(typeof(Key)).Length; x++)
                    {
                        // Check for main and alternate key
                        if ((Key)x == this.extendedKeystrokeEngine.GetMapping((GestureCommand)i))
                        {
                            keyMap.SelectedIndex = x + 1;
                        }

                        if ((Key)x == this.extendedKeystrokeEngine.GetAlternateMapping((GestureCommand)i))
                        {
                            alternateMap.SelectedIndex = x;
                        }
                    }
                }
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Handles key map changed and disables second combo box with control
        /// </summary>
        /// <param name="sender">
        /// Sender of the selection changed event
        /// </param>
        /// <param name="e">
        /// Event arguments
        /// </param>
        private void OnComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ComboBox comboBox = (ComboBox)sender;

            // Disable alternate key box, if user selected take control action
            int row = Grid.GetRow(comboBox);
            int column = Grid.GetColumn(comboBox);

            if (column == 1)
            {
                Logger.Trace(
                    "EventDetail: ComboBoxSelectionChanged - Row: {0}, Column: {1}, SelectedIndex: {2}", 
                    row, 
                    column, 
                    comboBox.SelectedIndex);

                // Handle take control command
                if (comboBox.SelectedIndex == 0)
                {
                    Logger.Trace("EventDetail: ComboBoxSelectionChanged - SetControlGesture");

                    this.extendedKeystrokeEngine.ControlGesture = (GestureCommand)row;
                }
                else
                {
                    Logger.Trace("EventDetail: ComboBoxSelectionChanged - SetMapping");

                    if ((GestureCommand)row == this.extendedKeystrokeEngine.ControlGesture)
                    {
                        this.extendedKeystrokeEngine.ControlGesture = GestureCommand.None;
                    }

                    this.extendedKeystrokeEngine.SetMapping((GestureCommand)row, (Key)(comboBox.SelectedIndex - 1));
                }

                ComboBox alternate =
                    (ComboBox)
                    this.SettingGrid.Children.Cast<UIElement>()
                        .First(el => (Grid.GetRow(el) == row) && (Grid.GetColumn(el) == 2));

                if (comboBox.SelectedIndex <= 1)
                {
                    alternate.SelectedIndex = 0;
                    alternate.IsEnabled = false;
                }
                else
                {
                    alternate.IsEnabled = true;
                }
            }
            else
            {
                Logger.Trace("MethodDetail: ComboBoxSelectionChanged - SetAlternateMapping");

                this.extendedKeystrokeEngine.SetAlternateMapping((GestureCommand)row, (Key)comboBox.SelectedIndex);
            }
        }

        #endregion
    }
}